package work.thread_eg.pool.demo;


import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 使用可缓存线程池
 *
 *
 */
@Slf4j
public class CachedThreadPoolMain01 {

    public static void main(String[] args) {
        CachedThreadPoolMain01 cachedThreadPoolMain = new CachedThreadPoolMain01();

        cachedThreadPoolMain.work();

    }

    public void work() {
        // 可缓存线程池
        ExecutorService threadPool = Executors.newCachedThreadPool();

        List<Integer> arrList = Stream.of(1, 2, 3, 4, 5).collect(Collectors.toList());

        List<FutureTask<Integer>> futureTaskList =  arrList.stream()
                .map(k->new FutureTask<>(new CountCallable(k))).collect(Collectors.toList());
        // 执行线程
        futureTaskList.forEach(threadPool::execute);

        // 统计的结果
        Integer sum = 0;

        System.out.println(new Date());
        for(FutureTask<Integer> task: futureTaskList) {
            try {
                // 这边是依次遍历futureTaskList 依次执行get()
                // 如果某个FutureTask执行get()的时候 对应的线程还没有执行完 就会阻塞在这里
                // 所有原则上这边不会有线程安全问题
                Integer count = task.get();
                System.out.println("线程执行结果" + count);
                sum = sum + count;
            }catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
        System.out.println(new Date());

        System.out.println("统计结果: " + sum);
        System.out.println("线程执行结束");

        // 关闭线程池 否则主进程结束不了 关闭后就不能有执行新的线程任务了
        threadPool.shutdown();
    }

    class CountCallable implements Callable<Integer> {
        /**
         * 数量
         */
        private  Integer count;

        public CountCallable(Integer count) {
            this.count = count;
        }

        /**
         * 计算处理
         *
         * @return
         * @throws Exception
         */
        @Override
        public Integer call() throws Exception {
            System.out.println("当前执行线程的名字: " + Thread.currentThread().getName());

            TimeUnit.SECONDS.sleep(5);
            return count + 10;
        }
    }


}
